/** * Base Model will be extended by all components. This class has utility methods and variables which are required at a framework level.
* This file specifies all those functions which are dependent on [KnockoutJS]{@link http://knockoutjs.com}. * @module baseModel * @requires jquery * @requires knockout * @requires ojs/ojcore * @requires base-model * @requires knockout-mapping * @requires base-models/validations/validations * @requires base-models/ko/formatters * @requires base-models/ko/help * @requires base-models/ko/custom-bindings * @requires knockout-helper * @requires framework/js/constants/constants * @requires extensions/extension.json */ define([ "ojs/ojcore", "knockout", "jquery", "base-model", "base-models/validations/validations", "base-models/ko/help", "ojL10n!resources/nls/generic", "framework/js/constants/constants", "text!extensions/extension.json", "base-models/ko/custom-bindings", "knockout-helper", "ojs/ojknockout" ], function (oj, ko, $, BaseModel, Validations, Help, Locale, Constants, extensions, jsonCallBack) { "use strict"; /** * Base Model will be extended by all components. This class has utility methods and variables which are required at a framework level.
* This file specifies all those functions which are dependent on [KnockoutJS]{@link http://knockoutjs.com}. * @class * @alias BaseKOModel * @memberof module:baseModel */ var BaseKOModel = function () { /** * Assign this to self. * @member {Object} */ var self = this; ko.utils.extend(self, new BaseModel()); ko.utils.extend(self, new Validations()); ko.utils.extend(self, new Help(self)); /** * This variable hold the object for current extentions. * @type {Object} */ var Extensions = JSON.parse(extensions); // ======================= SCB ======================== self.checkAndShowError = function (data) { //1. if (data == null || data.status == null) { return false; } //validate error if (data.responseJSON != null && data.responseJSON.message != null) { if (data.responseJSON.message.validationError != null && data.responseJSON.message.validationError.length > 0 && data.responseJSON.message.validationError[0] != null && data.responseJSON.message.validationError[0].errorMessage != null) { var errorCode = data.responseJSON.message.validationError[0].errorCode; if (errorCode == "DIGX_FU_048" || errorCode == "DIGX_AUTH_0013" || errorCode =="DIGX_SCB_GEN_500") { self.showMessages(data, null, null, function () { history.back(); window.onbeforeunload = null; }); return true; } else { self.showMessages(null, [data.responseJSON.message.validationError[0].errorMessage], 'ERROR'); return true; } } else { var messageCode = data.responseJSON.message.code; if (messageCode === "DIGX_FL_059") { self.showMessages(data, null, null, function () { history.back(); window.onbeforeunload = null; }); return true; } else { self.showMessages(null, [data.responseJSON.message.detail], 'ERROR'); return true; } } } //message if (data.status.message != null && data.status.message.relatedMessage != null && data.status.message.relatedMessage != null && data.status.message.relatedMessage.length > 0 && data.status.message.relatedMessage[0] != null && data.status.message.relatedMessage[0].code != 'DIGX_SCB_BPT_00') { self.showMessages(null, [data.status.message.relatedMessage[0].detail], 'ERROR'); return true; } return false; }; self.setDataDTOApproval = function (myself, source) { if (source) { myself.isLoadedForApproval(false); myself.d(source); myself.isLoadedForApproval(true); } else { console.log('===== ' + myself.loadComponentName() + '-KHONG CO DATA ====='); } }; self.dictAdd = function (dicarray, p_name, p_value) { var obj = ko.toJS(dicarray); if (obj == null || obj[0] == null || obj[0]['nameValuePairDTOArray'] == null) { console.log('nameValuePairDTOArray is null'); return obj; } var field = { "name": p_name, "value": p_value }; //console.log('nameValuePairDTOArray:' + obj[0]['nameValuePairDTOArray'].length); if ((obj[0]['nameValuePairDTOArray'][0]['name'] == null || obj[0]['nameValuePairDTOArray'][0]['name'] === '') && (obj[0]['nameValuePairDTOArray'][0]['value'] == null || obj[0]['nameValuePairDTOArray'][0]['value'] === '')) { obj[0]['nameValuePairDTOArray'][0]['name'] = p_name; obj[0]['nameValuePairDTOArray'][0]['value'] = p_value; return obj; } //console.log('nameValuePairDTOArray:' + obj[0]['nameValuePairDTOArray'].length); //them 1 cai khac. Copy tu cai thu 0 // obj[0]['nameValuePairDTOArray'].push(obj[0]['nameValuePairDTOArray'][0]); // var lastposition = obj[0]['nameValuePairDTOArray'].length - 1; // obj[0]['nameValuePairDTOArray'][lastposition]['name'] = p_name; // obj[0]['nameValuePairDTOArray'][lastposition]['value'] = p_value; obj[0]['nameValuePairDTOArray'].push(field); return obj; } self.dictGetValueByName = function (dicarray, p_name) { var obj = ko.toJS(dicarray); if (obj == null || obj[0] == null || obj[0]['nameValuePairDTOArray'] == null) { console.log('nameValuePairDTOArray is null'); return obj; } for (var i = 0; i < obj[0]['nameValuePairDTOArray'].length; i++) { if (obj[0]['nameValuePairDTOArray'][i]['name'] === p_name || obj[0]['nameValuePairDTOArray'][i]['genericName'] === p_name) { return obj[0]['nameValuePairDTOArray'][i]['value']; } } } //Khai bao nut back self.callBackPage = function (transname, currentpage) { //var obj1 = '{"flowPage":{"transactionNames":[{"card-lock-unlock":[{"currentPage":"card-lock","backPage":"scb-cards","headerTitleBackPage":"Thẻ","baseModel":""},{"currentPage":"scb-cards-review","backPage":"card-lock","headerTitle":"Khóa/Mở khóa thẻ","baseModel":""},{"currentPage":"scb-cards-result","backPage":"card-lock-unlock","headerTitle":"Khóa/Mở khóa thẻ","baseModel":""}]}]}}'; //var obj = cobj1); self.methodAction = ko.observable(jsonCallBack); //self.methodAction = JSON.parse(jsonCallBack); //ko.util.toJs(); self.methodList = ko.observableArray(self.methodAction().flowPage.transactionNames); //Object.entries(ii)[0][0] //Object.entries(ii)[0][1] : 3 phan tu //Object.entries(ii)[0][1][0].backPage for (var i = 0; i < self.methodList().length; i++) { var keyname = Object.entries(self.methodList()[i])[0][0]; //Object.keys(self.methodList()[i]); if (keyname === transname) { var ii = self.methodList()[i]; var mangcon3pt = Object.entries(ii)[0][1]; //chay for de quet cac page trong chuc nang nay for (var y = 0; y < mangcon3pt.length; y++) { if (mangcon3pt[y].currentPage === currentpage) { rootParams.baseModel.componentName = mangcon3pt[y].backPage; rootParams.baseModel.componentParams = self; rootParams.dashboard.headerName(mangcon3pt[y].headerTitle); rootParams.dashboard.loadComponent(rootParams.baseModel.componentName, {}, rootParams.baseModel.componentParams); } } } } }; self.remove_vn_accents = function (str) { if (typeof str != 'string') return null; str = str.replace(/(á|à|ả|ã|ạ|ă|ắ|ằ|ẳ|ẵ|ặ|â|ấ|ầ|ẩ|ẫ|ậ)/g, 'a'); str = str.replace(/(A|Á|À|Ả|Ã|Ạ|Ă|Ắ|Ằ|Ẳ|Ẵ|Ặ|Â|Ấ|Ầ|Ẩ|Ẫ|Ậ)/g, 'A'); str = str.replace(/đ/g, 'd'); str = str.replace(/Đ/g, 'D'); str = str.replace(/(é|è|ẻ|ẽ|ẹ|ê|ế|ề|ể|ễ|ệ)/g, 'e'); str = str.replace(/(É|È|Ẻ|Ẽ|Ẹ|Ê|Ế|Ề|Ể|Ễ|Ệ)/g, 'E'); str = str.replace(/(í|ì|ỉ|ĩ|ị)/g, 'i'); str = str.replace(/(Í|Ì|Ỉ|Ĩ|Ị)/g, 'I'); str = str.replace(/(ó|ò|ỏ|õ|ọ|ô|ố|ồ|ổ|ỗ|ộ|ơ|ớ|ờ|ở|ỡ|ợ)/g, 'o'); str = str.replace(/(Ó|Ò|Ỏ|Õ|Ọ|Ô|Ố|Ồ|Ổ|Ỗ|Ộ|Ơ|Ớ|Ờ|Ở|Ỡ|Ợ)/g, 'O'); str = str.replace(/(ú|ù|ủ|ũ|ụ|ư|ứ|ừ|ử|ữ|ự)/g, 'u'); str = str.replace(/(Ú|Ù|Ủ|Ũ|Ụ|Ư|Ứ|Ừ|Ử|Ữ|Ự)/g, 'U'); str = str.replace(/(ý|ỳ|ỷ|ỹ|ỵ)/g, 'y'); str = str.replace(/(Ý|Ỳ|Ỷ|Ỹ|Ỵ)/g, 'Y'); return str; }; // ======================= SCB ======================== if (window.cordova && window.device) { self.iPhoneX = window.device.model.includes('iPhone10,3') || window.device.model.includes('iPhone10,6'); } /** * Knockout Observable which returns boolean true/false depending on whether the screen is large and above. * @instance * @memberof BaseKOModel * @alias large * @type {Observable.} */ self.large = oj.ResponsiveKnockoutUtils.createMediaQueryObservable(oj.ResponsiveUtils.getFrameworkQuery( oj.ResponsiveUtils.FRAMEWORK_QUERY_KEY.LG_UP)); /** * Knockout Observable which returns boolean true/false depending on whether the screen is medium sized only. * @instance * @memberof BaseKOModel * @alias medium * @type {Observable.} */ self.medium = oj.ResponsiveKnockoutUtils.createMediaQueryObservable(oj.ResponsiveUtils.getFrameworkQuery( oj.ResponsiveUtils.FRAMEWORK_QUERY_KEY.MD_ONLY)); /** * Knockout Observable which returns boolean true/false depending on whether the screen is small only. * @instance * @memberof BaseKOModel * @alias small * @type {Observable.} */ self.small = oj.ResponsiveKnockoutUtils.createMediaQueryObservable(oj.ResponsiveUtils.getFrameworkQuery( oj.ResponsiveUtils.FRAMEWORK_QUERY_KEY.SM_ONLY)); /** * Knockout Observable which returns boolean true/false depending on whether the screen is extra large and above. * @instance * @memberof BaseKOModel * @alias xl * @type {Observable.} */ self.xl = oj.ResponsiveKnockoutUtils.createMediaQueryObservable(oj.ResponsiveUtils.getFrameworkQuery( oj.ResponsiveUtils.FRAMEWORK_QUERY_KEY.XL_UP)); /** * Create a key in knockout object for mapping plugin. * @type {Object} */ require(["knockout-mapping"], function (mapping) { ko.mapping = mapping; }); /** * The current language of the page as determined from navigator or user requested value picked from sessionStorage. * @type {String} * @member */ // eslint-disable-next-line no-storage/no-browser-storage var language = sessionStorage.getItem("user-locale") || document.getElementsByTagName("html")[0].getAttribute("lang") || "en"; /** * Set the language [lang]{@linkcode BaseKOModel~lang} as locale for oj.Config so that localization for Oracle JET is properly set. * @type {Object} */ oj.Config.setLocale(language, function () { var direction = Constants.RTL_LOCALES.indexOf(language) === -1 ? "ltr" : "rtl"; document.getElementsByTagName("html")[0].setAttribute("dir", direction); document.getElementsByTagName("html")[0].setAttribute("lang", language); }); /** * Array to store the list of authorized components for a particular user which will be consumed by * [knockout custom component loader]{@linkcode BaseKOModel~componentCustomLoader}. * @instance * @memberof BaseKOModel * @alias authorisedCompoList * @type {Observable.} */ self.authorisedCompoList = ko.observableArray([]); /** * Observable to store the time at which the last middleware request was fired.
* Declared inside [BaseKOModel]{@linkcode BaseKOModel} but is set in [service base]{@linkcode BaseService~genericCompleteHandler}. * @instance * @memberof BaseKOModel * @alias lastUpdatedTime * @type {Observable.} */ self.lastUpdatedTime = ko.observable(); /** * Knockout Custom Component loader to selectively load only those components which are specified in [authorisedCompoList]{@linkcode BaseKOModel#authorisedCompoList}.
* For more details, refer the [official KnockoutJS documentation]{@link http://knockoutjs.com/documentation/component-loaders.html#custom-component-loader}. * @type {Object} * @member */ var componentCustomLoader = { loadComponent: function (name, componentConfig, callback) { if (componentConfig.basePath === "components" && Extensions.components.indexOf(componentConfig.module + "/" + name) > -1) { componentConfig.basePath = "extensions/components"; } else if (componentConfig.basePath === "framework/elements" && Extensions.components.indexOf(componentConfig.module + "/" + name) > -1) { componentConfig.basePath = "extensions/elements"; } var componentPath = componentConfig.basePath + "/" + componentConfig.module + "/" + name + "/ko/bindings/" + name + "-bindings"; ko.components.defaultLoader.loadComponent(name, { require: componentConfig.compLoader ? componentConfig.compLoader(name, componentConfig, componentPath) : componentPath }, callback); } }; /** * Set the custom loader [componentCustomLoader]{@linkcode BaseKOModel~componentCustomLoader} as the primary Knockout component loader. * @type {Boolean} */ ko.components.loaders.unshift(componentCustomLoader); /** * Using deferUpdates as true reduces the UI clutter. Notifications happen asynchronously, immediately after the current task and generally before any UI redraws. * But you should take care because it will break code that depends on synchronous updates or on notification of intermediate values. Recommended workaround is using ko.tasks.runEarly(). * @type {Boolean} */ ko.options.deferUpdates = true; /** * The function to wrap a variable as an observable. * In case the value is already an observable, then the variable is not wrapped. * @instance * @function checkAndBindObservable * @memberof BaseKOModel * @param {Object} attr - The variable whose which has to be wrapped as an observable. * @param {Object} value - The default value of to initialize the variable with in case it is undefined. * @returns {Observable.<*>} - The variable wrapped as an observable. */ self.checkAndBindObservable = function (attr, value) { return ko.observable(ko.utils.unwrapObservable(attr) || value || ""); }; /** * This function is used to register a knockout component.
* Once a knockout component is registered, it can be used as a reusable template wherever required, * wherein both the component's template and view model shall be loaded. * * @function registerComponent * @instance * @param {String} componentId - The name of the component. * @param {object} moduleId - The module name the component is a part of. * @param {object} compLoader - Callback for component loader to be used while component registration. * @memberof BaseKOModel * @return {void} */ self.registerComponent = function (componentId, moduleId, compLoader) { var basePath = "components"; if (!ko.components.isRegistered(componentId)) { ko.components.register(componentId, { basePath: basePath, module: moduleId, compLoader: compLoader }); } }; /** * This function is used to register a OBDX core elements.
* Once a knockout component is registered, it can be used as a reusable template wherever required, * wherein both the component's template and view model shall be loaded. * * @function registerElement * @instance * @param {String} components - The name of the component. * @param {object} [moduleId = 'api'] - The module name the component is a part of. * @memberof BaseKOModel * @return {void} */ self.registerElement = function (components, moduleId) { var basePath = "framework/elements"; if (!Array.isArray(components)) components = [components]; components.forEach(function (componentId) { if (!ko.components.isRegistered(componentId)) { ko.components.register(componentId, { basePath: basePath, module: moduleId || "api" }); } }); }; /** * Converts a javascript object to JSON string implemenation.
* Uses [trimPayload]{@linkcode BaseModel#trimPayload} as replacer function for JSON.stringify. * @function removeTempAttributes * @instance * @memberof BaseKOModel * @param {Object} data The javascript object to be converted. * @return {String} JSON string is returned. */ self.removeTempAttributes = function (data) { return JSON.stringify(ko.toJS(data), self.trimPayload); }; self.messages = ko.observableArray(); /** * This function is used to display the server side error message or devloper configured messages.
* Registers and opens a new component message-box for displaying the error messages. * @function showMessages * @memberof BaseKOModel * @instance * @param {Object} jqXHR - The jqXHR object of the ajax call.
* Used to extract server sent error messages by [service base]{@linkcode BaseService~genericCompleteHandler}. * @param {Array.} errorsMessages - Sets the custom error message(s) to be thrown.
* The server needn't throw any error, set this property to thow user customized message(s).
Pass null as first argument in such cases. * @param {String} messageType - The type of message intended, is compulsory if custom message is being thrown.
* Can assume following values, * ERROR, INFO, SUCCESS or NOTIFICATION. * @param {Function} [onClose] - Function to be called when message box opened by this function is closed. * @returns {void} */ self.showMessages = function (jqXHR, errorsMessages, messageType, onClose) { self.messages.push({ response: jqXHR, errors: errorsMessages, type: messageType, onClose: onClose, id: Math.ceil((Math.random() * 9999999999) + 1) }); }; self.language = language; /** * Generic method to invoke authorization screen (OTP Screen, HOTP Screen, etc). * @param {Object} jqXHR The jqXHR object of the ajax call. * @param {Object} context The context of the request to be passed forward. * @param {Function} requestFunction The request function to invoke the middleware request again with authorization credentials.
* Can be [fireAjax]{@linkcode BaseService#fireAjax} or [getNonceForServiceInstance]{@linkcode BaseService~getNonceForServiceInstance}. * @param {Function} successHandlerFunction The success handler of the middleware request. * @returns {void} */ self.showAuthScreen = function (jqXHR, context, requestFunction, successHandlerFunction) { var authViewModel = { baseModel: self, serverResponse: jqXHR, currentContext: context, fireRequest: requestFunction, originalSuccess: successHandlerFunction, registerComponent: self.registerComponent, currentIdCount: self.currentIdCount, incrementIdCount: self.incrementIdCount }; self.registerComponent("generic-authentication", "base-components"); $("#authScreenWindow").remove(); var parent = document.createElement("div"); parent.setAttribute("data-bind", "component : {name: \"generic-authentication\", params:{rootModel: $data, id : \"authScreenWindow\"}}"); parent.id = "authScreenWindow"; $("main.container").append(parent); $("div.primarycontent").hide(); ko.applyBindings(authViewModel, document.getElementById("authScreenWindow")); }; /** * Switch the language of the application. * @function setLocale * @instance * @memberof BaseKOModel * @param {String} newLanguage - The language to be set.
* Use valid ISO 639-1 language code. * @returns {void} */ self.setLocale = function (newLanguage) { if (language !== newLanguage) { // eslint-disable-next-line no-storage/no-browser-storage sessionStorage.setItem("user-locale", newLanguage); window.location.reload(); } }; function addZero(i) { if (i < 10) { i = "0" + i; } return i; }; /** * This method used for getting server date time on user desired format * @function getDate * @instance * @memberof BaseKOModel * @param {String} [dateType] - Desired format of server date.
* Use valid ISO 639-1 language code. * @returns {Date} */ self.getDate = function (dateType) { var date = new Date(Constants.currentServerDate.getTime()); if (Constants.timezoneOffset) { date.setMinutes(date.getMinutes() + date.getTimezoneOffset() + (-1 * Constants.timezoneOffset)); } switch (dateType) { case "DATE_TIME": return date; case "DATE_TIME_PRINF": return addZero(date.getDate()) + '/' + addZero(date.getMonth()+1) + '/' + date.getFullYear() + ' ' + addZero(date.getHours())+ ':'+ addZero(date.getMinutes()); default: return new Date(date.toDateString()); } }; /** * Returns the ISO 639-1 of the current language of the application. * @function getLocale * @instance * @memberof BaseKOModel * @return {String} The ISO 639-1 code of the language. */ self.getLocale = function () { return oj.Config.getLocale(); }; /** * Extends the formatter instance returned from dashboard-binding. * @param {Formatter} Formatter Instance of {@linkcode Formatter}. * @returns {void} */ self.setFormatter = function (Formatter) { ko.utils.extend(self, Formatter); }; /** * The global error handler for RequireJS.
* To detect errors that are not caught by local errbacks, this overriden implemenation of requirejs.onError() is used. * @function onError * @inner * @callback * @memberof BaseKOModel * @param {Object} err The error object returned by RequireJS. * @returns {void} */ require.onError = function (err) { if (console && console.error) console.error(err); if (err.requireType === "timeout" || err.requireType === "scripterror") { self.showMessages(null, [Locale.error], "ERROR", function () { window.location.reload(); }); } }; }; /** * Holds the instance of [BaseKOModel]{@linkcode BaseKOModel} * @memberof module:baseModel * @inner * @type {BaseKOModel} */ var instance; return { /** * Get the base model instance. Checks [instance]{@linkcode module:baseModel~instance} for instance. * @function getInstance * @memberof module:baseModel * @static * @returns {BaseKOModel} The base service instance. */ getInstance: function () { if (!instance) { instance = new BaseKOModel(); } return instance; } }; });